/**
 * 
 */
package com.bitBusy.manageyourriches.database.managers;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import android.content.Context;

import com.bitBusy.manageyourriches.R;
import com.bitBusy.manageyourriches.database.contactClasses.ExpenseDetails;
import com.bitBusy.manageyourriches.database.contactClasses.PaymentMethod;
import com.bitBusy.manageyourriches.database.contactClasses.PaymentReminder;
import com.bitBusy.manageyourriches.database.contactClasses.SpendingCategory;
import com.bitBusy.manageyourriches.database.contactClasses.SpendingSubcategory;
import com.bitBusy.manageyourriches.database.queries.QueriesBasicDetailsTable;
import com.bitBusy.manageyourriches.database.queries.QueriesCategoryImagesTable;
import com.bitBusy.manageyourriches.database.queries.QueriesPaymentInfoTable;
import com.bitBusy.manageyourriches.database.queries.QueriesPaymentRemindersTable;
import com.bitBusy.manageyourriches.database.queries.QueriesPreviouslyChosenValuesTable;
import com.bitBusy.manageyourriches.database.queries.QueriesSubcategoryCategoryTable;
import com.bitBusy.manageyourriches.utilityClasses.checkers.NullChecker;
import com.bitBusy.manageyourriches.utilityClasses.filehandlers.ReportFileBuilder;

/**
 * Class that holds methods to add new values
 * to one or more of the primary key columns of tables in the db
 * @author SumaHarsha
 *
 */
public class DatabaseInteractor {

	/**Context*/
	private Context myContext;
	
	/**
	 * @param the_context DB context
	 * @param the activity context
	 */
	public DatabaseInteractor(Context the_context) {
		myContext = the_context;
	}

		/**Default subcategory names array*/
	private static final String[] SUBCATEGORYARRAY = 
			new String[]{"general"};
	
	/**Default category image id*/
	private static final int DEFAULTCATEGORYIMAGE = 
			R.drawable.user_def;

	/**Default payment method image id*/
	private static final int DEFAULTPAYMENTIMAGE = 
			R.drawable.paymentmethod;

	
	/** Method to add a new category into the tables
	 * @param name of the category*/
	public void addCategory(String the_categoryName)
	{
		if(the_categoryName != null)
		{
				Map<String, Integer> insertMap = new HashMap<String, Integer>();
				insertMap.put(the_categoryName, DEFAULTCATEGORYIMAGE);
				new QueriesCategoryImagesTable(myContext).addCategories(insertMap);	
				
				Map<String, Integer> insertSubcatMap = new HashMap<String, Integer>();
				for(int i = 0; i <SUBCATEGORYARRAY.length; i++)
				{
					insertSubcatMap.put(SUBCATEGORYARRAY[i], DEFAULTCATEGORYIMAGE);
				}
				new QueriesSubcategoryCategoryTable(myContext).addSubcategories(the_categoryName, insertSubcatMap);
		}
	}
	
	
	/** Method to add a new subcategory into the tables
	 * @param name of the category
	 * @param name of the subcategory
	 * @param the context
	 */
	public void addSubcategory(String the_categoryName, int the_categoryPicID, String the_subcategoryName)
	{
		if(the_categoryName != null &&the_subcategoryName != null)
		{
				Map<String, Integer> subcategory = new HashMap<String, Integer>();
				subcategory.put(the_subcategoryName, the_categoryPicID);
				new QueriesSubcategoryCategoryTable(myContext).addSubcategories(the_categoryName,subcategory);
		}
	}

		

	/** Method to add a new payment method to the PaymentInfo table
	 * @param the context
	 * @param the name of the payment method
	 */
	public void addPaymentMethod(String the_paymentMethod)
	{
		if (the_paymentMethod != null)
		{
			Map<String, Integer> paymentMethod = new HashMap<String, Integer>();
			paymentMethod.put(the_paymentMethod,DEFAULTPAYMENTIMAGE);
			new QueriesPaymentInfoTable(myContext).addPaymentMethods(paymentMethod);
		}
	}
	
	/**
	 * Method to add row to basic details table
	 * @param the_subcategory
	 * @param the_category
	 * @param expense details
	 * @return boolean indicating if row was successfully added
	 */
	public boolean addExpenseDetails(String the_subcategory, String the_category,ExpenseDetails the_expense)
	{
		if (!NullChecker.checkForNullValues(new Object[]{the_subcategory, the_category, the_expense})
				&& (new QueriesBasicDetailsTable(myContext).
				addRow(the_subcategory, the_category, the_expense) > -1))
		{
			return true; 
		}
		return false;
	}
	
	/**
	 * Method to get previous subcategory choice for category
	 * @param the_categoryName
	 * @return the name of category
	 */
	public String getPrevChosenSubcategory(String the_categoryName)
	{
		if (the_categoryName != null)
		{
			return new QueriesPreviouslyChosenValuesTable(myContext).getChosenSubcategory(the_categoryName);
		}
		return null;
	}
	
	/**
	 * Method to get previous payment method choice for category
	 * @param the_categoryName
	 * @return the name of payment method
	 */
	public String getPrevChosenPaymentMethod(String the_categoryName)
	{
		if (the_categoryName != null)
		{
			return new QueriesPreviouslyChosenValuesTable(myContext).getChosenPaymentMethod(the_categoryName);
		}
		return null;
	}
	
	/**
	 * Method to get a list of subcategory names for a given category
	 * @param category name 
	 * @return map of subcategory names and image ids
	 */
	public LinkedHashMap<String, Integer> getSubcategories(String the_categoryName)
	{
		if (the_categoryName != null)
		{
			return new QueriesSubcategoryCategoryTable(myContext).getSubcategories(the_categoryName);
		}
		return null;
	}
	
	
	/**
	 * Method to return a list of all payment method names
	 * @return the map of names and images
	 */
	public LinkedHashMap<String, Integer> getAllPaymentInfo()
	{
		return new QueriesPaymentInfoTable(myContext).getAllPaymentMethodsAndImages();
	}

	
	public LinkedHashMap<String, Integer> getAllCategoriesAndImages()
	{
		return new QueriesCategoryImagesTable(myContext).getAllCategoriesAndImages();
	}
	
	/**Save choice for subcategory spinner, for this category
	 * @param the category name
	 * @param the subcategory name
	 */
	public void saveSubcategoryChoice(String the_categoryName, String the_subcategoryName)
	{
		if (the_categoryName != null && the_subcategoryName != null)
		{
			 new QueriesPreviouslyChosenValuesTable(myContext).rememberSubcategory(the_categoryName, the_subcategoryName);
		}
	}
	
	
	/**Save choice for payment info spinner, for this category
	 * @param the category name
	 * @param the payment method name
	 */
	public void savePaymentMethodChoice(String the_categoryName, String the_paymentMethodName)
	{
		if (the_categoryName != null && the_paymentMethodName != null)
		{
			 new QueriesPreviouslyChosenValuesTable(myContext).rememberPaymentMethod(the_categoryName, the_paymentMethodName);
		}
	}
	
	/**Method to get all payment methods
	 * @return list of payment methods
	 */
	public LinkedList<PaymentMethod> getAllPaymentMethods()
	{
		LinkedList<PaymentMethod> paymentMethods = new LinkedList<PaymentMethod>();
		LinkedHashMap<String, Integer> methodImgs = getAllPaymentInfo();
		if (methodImgs != null)
		{
			for(Entry<String, Integer> mapEntry:methodImgs.entrySet())
			{
				String name = mapEntry==null?null:mapEntry.getKey();
				int imgID = mapEntry==null?R.drawable.user_def:mapEntry.getValue();
				//List<SpendingSubcategory> subcategories = getAllSpendingSubcategories(name);
				PaymentMethod method = new PaymentMethod(name,imgID);
				paymentMethods.add(method);
			}
		}
		return paymentMethods;
	}
	
	/**Method to get all spending category objects
	 * @return list of spending category objects
	 */
	public LinkedList<SpendingCategory> getAllSpendingCategories()
	{
		LinkedList<SpendingCategory> categories = new LinkedList<SpendingCategory>();
		LinkedHashMap<String, Integer> categoryImgs = getAllCategoriesAndImages();
		if (categoryImgs != null)
		{
			for(Entry<String, Integer> mapEntry:categoryImgs.entrySet())
			{
				String name = mapEntry==null?null:mapEntry.getKey();
				int imgID = mapEntry==null?R.drawable.user_def:mapEntry.getValue();
				List<SpendingSubcategory> subcategories = getAllSpendingSubcategories(name);
				SpendingCategory category = new SpendingCategory(name,imgID, subcategories);
				categories.add(category);
			}
		}
		return categories;
	}
	
	/**Method to get all spending subcategory objects
	 * @param name of category
	 * @return list of spending subcategory objects
	 */
	public LinkedList<SpendingSubcategory> getAllSpendingSubcategories(String the_categoryName)
	{
		LinkedList<SpendingSubcategory> subcategories = new LinkedList<SpendingSubcategory>();
		LinkedHashMap<String, Integer> subcategoryImgs = getSubcategories(the_categoryName);
		if (subcategoryImgs != null)
		{
			for(Entry<String, Integer> mapEntry:subcategoryImgs.entrySet())
			{
				String name = mapEntry==null?"":mapEntry.getKey();
				int imgID = mapEntry==null?R.drawable.user_def:mapEntry.getValue();
				SpendingSubcategory subcategory = new SpendingSubcategory(name, the_categoryName, imgID);
				subcategories.add(subcategory);
			}
		}
		return subcategories;
	}
	
	/**Method to get total amount spent for asked duration
	 * @param from date
	 * @param to date
	 * @return double value of amount
	 */
	public double getTotalSpent(int myFromDate, int myToDate)
	{
		double sum = 0;
			sum = new QueriesBasicDetailsTable(myContext).getTotalSpent(
					myFromDate,myToDate);
		return sum;
	}
	
	/**Get total spent for a spending category in a period of time
	 * @param category name
	 * @param from date
	 * @param to date
	 * @return total spent
	 */
	public double getTotalSpentCategory(String the_categoryName, int the_fromDate, int the_toDate)
	{
		double sum = 0;
		sum = new QueriesBasicDetailsTable(myContext).getTotalSpentCategory(the_categoryName, 
					the_fromDate, the_toDate);
		return sum;
	
	}
	
	
	/**Get total spent for a payment method in a period of time
	 * @param method name
	 * @param from date
	 * @param to date
	 * @return total spent
	 */
	public double getTotalSpentPaymentMethod(String the_methodName, int the_fromDate, int the_toDate)
	{
		double sum = 0;
		sum = new QueriesBasicDetailsTable(myContext).getTotalSpentPaymentMethod(the_methodName, 
					the_fromDate, the_toDate);
		return sum;
	
	}
	
	

	
	/**Get total spent for a spending subcategory in a period of time
	 * @param category name
	 * @param subcategory name
	 * @param from date
	 * @param to date
	 * @return total spent
	 */
	public double getTotalSpentSubcategory(String the_categoryName,String the_subcategoryName, int the_fromDate, int the_toDate)
	{
		double sum = 0;
		sum = new QueriesBasicDetailsTable(myContext).getTotalSpentSubcategory
					(the_categoryName, the_subcategoryName,the_fromDate, the_toDate);
		return sum;
	
	}
	


	/**
	 * Method to get list of ExpenseDetails for given category and subcategory
	 * @param parentCategory
	 * @param name
	 * @return list of expense details
	 */
	public List<ExpenseDetails> getExpenses(String the_parentCategory, String the_subcategory, int the_fromDate, int the_toDate) {
		if (the_parentCategory != null &&  the_subcategory != null)
		{
			 return new QueriesBasicDetailsTable(myContext).getExpenses
				(the_parentCategory, the_subcategory, the_fromDate, the_toDate);

		}
		return null;
	}
	
	/**
	 * Deletes an expense record
	 * @param the_parentCategory
	 * @param the_subcategory
	 * @param the_expense
	 * @return
	 */
	public boolean deleteRecord(String the_parentCategory, String the_subcategory, ExpenseDetails the_expense)
	{
		return new QueriesBasicDetailsTable(myContext).deleteRecord(the_parentCategory, the_subcategory, the_expense);
	}


	/**
	 * gets datewise  spending for a given period
	 * @param the_from date 
	 * @param the to date
	 * @return map of date and amount
	 */
	public LinkedHashMap<String, Double> getDatewiseSpending(
			int the_fromDate, int the_toDate) {
		
		return new QueriesBasicDetailsTable(myContext).getDatewiseSpending(the_fromDate, the_toDate);
		}


	/**
	 * returns total spending for a particular period
	 * @param fromYear
	 * @param toYear
	 * @return
	 */
	public LinkedHashMap<String, Double> getYearWiseSpending(int the_fromYear,
			int the_toYear) {
		return new QueriesBasicDetailsTable(myContext).getYearWiseSpending(the_fromYear, the_toYear);
	}


	/**
	 * total spending for a particular period
	 * @param fromMonth
	 * @param toMonth
	 * @return
	 */
	public LinkedHashMap<String, Double> getMonthwiseSpending(int the_fromMonth,
			int the_toMonth) {
		return new QueriesBasicDetailsTable(myContext).getMonthwiseSpending(the_fromMonth, the_toMonth);
	}


	/**
	 * @param parseForDBDate
	 * @param parseForDBDate2
	 * @return
	 */
	public LinkedHashMap<String, Double> getDaywiseSpending(int the_fromDate,
			int the_toDate) {
		return new QueriesBasicDetailsTable(myContext).getDaywiseSpending(the_fromDate, the_toDate);
	}


	/**
	 * @param parseForDBDate
	 * @param parseForDBDate2
	 * @return
	 */
	public LinkedHashMap<String, Double> getTimewiseSpending(
			int the_fromDate, int the_toDate) {
		return new QueriesBasicDetailsTable(myContext).getTimewiseSpending(the_fromDate, the_toDate);

	}


	/**
	 * @param the_calendar
	 * @return 
	 */
	public boolean saveAlarm(PaymentReminder the_reminder) {
		if (the_reminder != null)
		{
			return new QueriesPaymentRemindersTable(myContext).saveAlarm(the_reminder);
		}
		return false;
		
	}


	/**
	 * @param parcelable
	 * @return 
	 */
	public boolean deleteAlarm(PaymentReminder the_reminder) {
		if (the_reminder != null)
		{
			return new QueriesPaymentRemindersTable(myContext).deleteAlarm(the_reminder);
		}		
		return false;
	}


	/**
	 * @return
	 */
	public ArrayList<PaymentReminder> getAllNonRecurrentReminders() {
		return new QueriesPaymentRemindersTable(myContext).getAllNonRecurrentReminders();

	}
	
	/**
	 * @return
	 */
	public ArrayList<PaymentReminder> getAllReminders() {
		return new QueriesPaymentRemindersTable(myContext).getAllReminders();

	}
	
	

	/**
	 * @param the_fileBuilder 
	 * @return
	 */
	public void getReportTillDate(ReportFileBuilder the_fileBuilder) {
		 new QueriesBasicDetailsTable(myContext).getReportTillDate(the_fileBuilder);
	}


	/**
	 * @return
	 */
	public ArrayList<PaymentReminder> getAllRecurrentReminders() {
		return new QueriesPaymentRemindersTable(myContext).getAllRecurrentReminders();

	}


	/**
	 * @param categoryChosen
	 * @return 
	 */
	public boolean deleteCategory(String the_categoryChosen) {
		if (the_categoryChosen != null)
		{
			return 
			(new QueriesBasicDetailsTable(myContext).deleteCategory(the_categoryChosen) &&
			new QueriesPreviouslyChosenValuesTable(myContext).deleteCategory(the_categoryChosen) &&
			new QueriesSubcategoryCategoryTable(myContext).deleteCategory(the_categoryChosen) &&
			new QueriesCategoryImagesTable(myContext).deleteCategory(the_categoryChosen));
		}
		return false;
	}


	/**
	 * @param subcategory 
	 * @param subcategory
	 * @return
	 */
	public boolean deleteSubcategory(String the_category, String the_subcategory) {
		if (the_subcategory != null)
		{
			return 
			(new QueriesBasicDetailsTable(myContext).deleteSubcategory(the_category, the_subcategory)&&
			 new QueriesPreviouslyChosenValuesTable(myContext).deleteSubcategory(the_category, the_subcategory)&&
			 new QueriesSubcategoryCategoryTable(myContext).deleteSubcategory(the_category, the_subcategory));
		}
		return false;
	}
	

}


